﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
using System.ComponentModel;
using System.Windows.Threading;

namespace EstevesRecordersProject
{
    /// <summary>
    /// Interaction logic for LoadFile.xaml
    /// </summary>
    public partial class WindowLoadFile : Window
    {

        private readonly OpenFileDialog  chooseFileDialog = new OpenFileDialog();
        private String chosenFile;

        private String message;
        public String Message { 
            get { return message; } 
            set 
            { 
                message = value;

                if (lblMessage != null)
                {
                    if (lblMessage.Dispatcher.CheckAccess())
                    {    
                        lblMessage.Content = value;
                    }
                    else
                    {
                        lblMessage.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                            (Action)(() => { lblMessage.Content = value; }));
                    }
                }  
            } 
        }

        public void setMessageColor(Brush b)
        {
            if (lblMessage != null)
            {
                if (lblMessage.Dispatcher.CheckAccess())
                {
                    lblMessage.Foreground = b;
                }
                else
                {
                    lblMessage.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        (Action)(() => { lblMessage.Foreground = b; }));
                }
            }  
        }

        private Recorder recorder = null;
        private BackgroundWorker backgroundWorker = new BackgroundWorker();
        

        //from file
        private int countPerformance = 0;
        private int countPerformanceLines = 0;

        private void InitializeComboBoxRecorder()
        {
            List<Recorder> recorders = Repository.GetAllRecorders();
            comboBoxRecorder.ItemsSource = recorders;
            comboBoxRecorder.SelectedValuePath = "ID";
        }

        public WindowLoadFile()
        {
            InitializeComponent();

            InitializeComboBoxRecorder();

            chooseFileDialog.Title = "Choose report:";
            chooseFileDialog.Filter = " txt files (*.txt)|*.txt|All files (*.*)|*.*";
            chooseFileDialog.FilterIndex = 1;
            chooseFileDialog.RestoreDirectory = true;
            chooseFileDialog.FileOk += OnOpenFileDialogOK;

            lblMessage.Content = String.Empty;

            //progress bar
            progressBar.Minimum = 0;
            progressBar.Maximum = 100;
            progressBar.Value = 0;

            //background worker
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            backgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;
        }

        private List<Performance> LoadFile(String chosenFile)
        {
            StreamReader streamReader = new StreamReader(chosenFile);
            List<Performance> performanceList = new List<Performance>();

            if (recorder == null)
            {
                throw new NoRecorderSelectedException();
            }

            //sprawdza, czy data była juz wczytywana
            bool dataChecked = false;
            int nrOfRecorderLines = recorder.NrOfLines;
            int totalLinesCount = System.IO.File.ReadAllLines(chosenFile).Length;
            string recorderName = String.Empty;
            DateTime dateTime = new DateTime();
            int lineNr = 0;
            int value = 0;

            while ((!streamReader.EndOfStream))
            {
                String nextLine = streamReader.ReadLine();

                //pomin dwie pierwsze linie
                if (nextLine.StartsWith("\"#\"")) continue;
                else
                    if (nextLine.StartsWith("\""))
                    {
                        //"Plot Title: 2009492 "
                        //first position of : 
                        int x1 = nextLine.IndexOf(':') + 1;
                        String temp = "";
                        temp = nextLine.Substring(x1);
                        temp = temp.Substring(0, temp.Length - 1);
                        temp = temp.Trim();

                        //recorder name
                        recorderName = temp;

                        if (recorderName != recorder.name || recorderName != recorder.name2)
                        {
                            MessageBoxResult mbr = MessageBox.Show("Recorder name and name in the file aren't equal. Would you like to continnue? ", "Continnue?", MessageBoxButton.YesNo);
                            if (mbr == MessageBoxResult.No)
                            {
                                throw new ApplicationException("Action was canceled.");
                            }
                        }
                    }
                    else
                    //DANE
                    {
                        if (nextLine.Contains("Logged")) continue;

                        countPerformanceLines ++;
                        String temp = "";
                        int tabIndex;
                        
                        //numer zczytanej akcji
                        tabIndex = nextLine.IndexOf('\t');
                        temp = nextLine.Substring(0, tabIndex);
                        lineNr = Int32.Parse(temp);

                        //PROGRESS
                        int progress = (int)((lineNr * 100) / totalLinesCount);
                        backgroundWorker.ReportProgress(progress / 2);
                        //END PROEGRESS

                        //data
                        tabIndex = nextLine.IndexOf('\t') + 1;
                        temp = nextLine.Substring(tabIndex).TrimStart();
                        String tempDate = temp.Substring(0, 8);
                        
                        string day =  temp.Substring(0,2) ;
                        string month = temp.Substring(3, 2);
                        string year = temp.Substring(6, 2);

                        tempDate = year + "." + month + "." + day;

                        //czas
                        temp = temp.Substring(9).TrimStart();
                        String tempTime = temp.Substring(0, 8);


                        //AM - PM
                        temp = temp.Substring(9).TrimStart();
                        String ampm = temp.Substring(0, 2);

                        dateTime = DateTime.Parse( tempDate+ " " + tempTime);

                        //jesli PM i godzina inna niz 12, to dodaj 12h (zamiana na czas polski)
                        if (ampm.ToUpper() == "PM" && dateTime.Hour != 12)
                        {
                            dateTime = dateTime.AddHours(12);
                        }
                        
                        //wartosci
                        temp = temp.Substring(3);

                        for (int i = 1; i < nrOfRecorderLines + 1; i++)
                        {
                            if (temp[0] != '\t')
                            {
                                String v = temp.Substring(0, temp.IndexOf('\t')).Trim();
                                value = Int32.Parse(v[0].ToString());   //odczytana wartosc
                                temp = temp.Substring(temp.IndexOf('\t') + 1);  //przesuwany o jeden /t

                                //Create performance
                                Performance performance = new Performance();
                                performance.date = dateTime;
                                performance.idLinel = recorder.Line(i).id;
                                performance.value = value;
                                performance.id = -1;    //nie istotne

                                //check if date doesnt exist
                                if (!dataChecked)
                                {
                                    int chceck = Repository.CheckDate(Repository.GetLine(recorder.id, i).id, dateTime);
                                    if (chceck > 0)
                                    {
                                        MessageBoxResult mbr = MessageBox.Show("It seems, that data with given date was already loaded. Would you like to duplicate data? ", "Continnue?", MessageBoxButton.YesNo);
                                        if (mbr == MessageBoxResult.No){
                                            throw new ApplicationException("Action was canceled.");
                                        }
                                    }
                                    dataChecked = true;
                                }
                                //end check

                                performanceList.Add(performance);
                                countPerformance++;
                            }
                            else
                            {
                                //przesuwamy sie o 1 /t dalej
                                temp = temp.Substring(1);
                            }
                        }
                    }
            }

            streamReader.Close();
            return performanceList;
        }

        public void LoadToDatabase(List<Performance> performanceList)
        {

            for (int i = 0; i < performanceList.Count; i++)
            {
                //PROGRESS
                int progress = (int)((i * 100) / performanceList.Count);
                backgroundWorker.ReportProgress(50 + progress / 2);
                //END PROGRESS

                //insert to database
                Repository.AddNewPerformance(performanceList[i]);
            }
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.Cursor = Cursors.Wait;
                this.buttonLoadFile.IsEnabled = false;
                this.btnChooseFile.IsEnabled = false;

                //load from file and add to database
                backgroundWorker.RunWorkerAsync();  
            }
            catch (NoRecorderSelectedException ex)
            {
                Message = ex.Message;
                lblMessage.Foreground = Brushes.Red;
            }
            catch (ArgumentNullException)
            {
                Message = "Choose file.";
                lblMessage.Foreground = Brushes.Red;
            }
            catch (Exception ex)
            {
                Message = ex.Message;
                lblMessage.Foreground = Brushes.Red;
            }
            finally
            {
                this.Cursor = Cursors.Arrow;
            }
        }


        private void btnChooseFile_Click(object sender, RoutedEventArgs e)
        {
            chooseFileDialog.ShowDialog();
        }

        void OnOpenFileDialogOK(object sender, CancelEventArgs e)
        {

            try
            {
                chosenFile = chooseFileDialog.FileName;
                this.textBox1.Text = chooseFileDialog.FileName;           
            }
            catch (Exception ex)
            {
                Message = ex.Message;
                lblMessage.Foreground = Brushes.Red;
            }
        }

        private void comboBoxRecorder_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                recorder = (Recorder)comboBoxRecorder.SelectedItem;
            }
            catch(Exception ex)
            {
                Message = ex.Message;
                lblMessage.Foreground = Brushes.Red;
            }
        }

        //background worker
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                Message = "Reading from file ...";
                setMessageColor(Brushes.Black);
                List<Performance> performanceList = LoadFile(chosenFile);

                Message = "Inserting to database ...";
                setMessageColor(Brushes.Black);
                LoadToDatabase(performanceList);
            }
            catch (ApplicationException)
            {
                e.Cancel = true;
            }
            catch (Exception ex)
            {
                e.Result = ex.Message;
            }
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                this.buttonLoadFile.IsEnabled = true;
                this.btnChooseFile.IsEnabled = true;

                if (e.Result != null)
                {
                    Message = (String)e.Result;
                    lblMessage.Foreground = Brushes.Red;
                }
                else if (e.Cancelled)
                {
                    Message = "Action was canceled.";
                    setMessageColor(Brushes.Blue);
                }
                else
                {
                    this.progressBar.Value = 100;
                    Message = String.Format("All file's data saved successfully (performace lines: {0}, performace count: {1}).", countPerformanceLines, countPerformance);
                    lblMessage.Foreground = Brushes.Green;
                }
            }
            catch (Exception ex)
            {
                Message = ex.Message;
                lblMessage.Foreground = Brushes.Red;
            }

        }

        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar.Value = e.ProgressPercentage;
        }
    }
}
